﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace MVCToolkit.Controls
{
    public static class ControlHelper
    {
        public static IDictionary<string, object> GetHtmlAttributes<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression = null,
            object htmlAttributes = null,
            object dataAttributes = null,
            KOBinding<TModel>[] koBindAttributes = null,
            object koCustomBindAttributes = null,
            ControlType controlType = ControlType.Input,
            bool defaultKOBinding = true)
        {
            IDictionary<string, object> htmlAttributesDictionary = null;

            if (htmlAttributes != null)
            {
                htmlAttributesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            }
            else
            {
                htmlAttributesDictionary = new Dictionary<string, object>();
            }

            if (dataAttributes != null)
            {
                foreach (var dataItem in HtmlHelper.AnonymousObjectToHtmlAttributes(dataAttributes))
                {
                    htmlAttributesDictionary.Add("data-" + dataItem.Key, dataItem.Value);
                }
            }

            StringBuilder dataBindValue = new StringBuilder();
            StringBuilder dataBindCustomValues = new StringBuilder();

            if (koBindAttributes != null)
            {
                dataBindValue = new StringBuilder();
                foreach (var ksBindItem in koBindAttributes)
                {
                    string expressionText = ExpressionHelper.GetExpressionText(ksBindItem.Expression);
                    string[] tempArray = expressionText.Split('.');
                    string propertyName = tempArray[tempArray.Length - 1];

                    dataBindValue.Append(ksBindItem.HtmlAttribute);
                    dataBindValue.Append(":");
                    dataBindValue.Append(propertyName);
                    dataBindValue.Append(",");
                }
            }

            if (koCustomBindAttributes != null)
            {
                dataBindCustomValues = new StringBuilder();
                foreach (var dataItem in HtmlHelper.AnonymousObjectToHtmlAttributes(koCustomBindAttributes))
                {
                    dataBindCustomValues.Append(dataItem.Key);
                    dataBindCustomValues.Append(":");
                    dataBindCustomValues.Append(dataItem.Value);
                    dataBindCustomValues.Append(",");
                }
            }

            if (!String.IsNullOrWhiteSpace(dataBindValue.ToString()) && !String.IsNullOrWhiteSpace(dataBindCustomValues.ToString()))
            {
                htmlAttributesDictionary.Add("data-bind", dataBindValue.ToString().TrimEnd(',') + dataBindCustomValues.ToString().TrimEnd(','));
            }
            else if (!String.IsNullOrWhiteSpace(dataBindValue.ToString()))
            {
                htmlAttributesDictionary.Add("data-bind", dataBindValue.ToString().TrimEnd(','));
            }
            else if (!String.IsNullOrWhiteSpace(dataBindCustomValues.ToString()))
            {
                htmlAttributesDictionary.Add("data-bind", dataBindCustomValues.ToString().TrimEnd(','));
            }

            if (expression != null)
            {
                ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

                if (defaultKOBinding)
                {

                    if (!htmlAttributesDictionary.ContainsKey("data-bind"))
                    {
                        htmlAttributesDictionary.Add("data-bind", string.Empty);
                    }

                    string expressionText = ExpressionHelper.GetExpressionText(expression);
                    string[] tempArray = expressionText.Split('.');
                    string propertyName = tempArray[tempArray.Length - 1];
                    string htmlValueAttributeName = "value";

                    if (controlType == ControlType.Input || controlType == ControlType.Select)
                    {
                        htmlValueAttributeName = "value";
                    }
                    else if (controlType == ControlType.Checkbox || controlType == ControlType.RadioButton)
                    {
                        htmlValueAttributeName = "checked";
                    }

                    htmlAttributesDictionary["data-bind"] = !String.IsNullOrWhiteSpace(htmlAttributesDictionary["data-bind"].ToString()) ?
                        htmlAttributesDictionary["data-bind"].ToString() + "," + htmlValueAttributeName + ": " + propertyName :
                        htmlValueAttributeName + ": " + propertyName;
                }

                //Build html5 required attribute (http://www.w3schools.com/html5/html5_form_attributes.asp)
                if (metadata.IsRequired)
                {
                    htmlAttributesDictionary.Add("required", "required");
                }

                //Build html5 placeholder attribute (http://www.w3schools.com/html5/html5_form_attributes.asp)
                if (metadata.AdditionalValues.ContainsKey("html5placeholder") && metadata.AdditionalValues["html5placeholder"] != null)
                {
                    htmlAttributesDictionary.Add(new KeyValuePair<string, object>("placeholder", metadata.AdditionalValues["html5placeholder"]));
                }

                //Build html5 pattern attribute (http://www.w3schools.com/html5/html5_form_attributes.asp)
                object[] regularExpressionAttributes = typeof(TModel).GetProperty(metadata.PropertyName).GetCustomAttributes(typeof(RegularExpressionAttribute), false);

                if (regularExpressionAttributes != null && regularExpressionAttributes.Count() > 0)
                {
                    htmlAttributesDictionary.Add("pattern", ((RegularExpressionAttribute)regularExpressionAttributes[0]).Pattern);
                }
            }

            return htmlAttributesDictionary;
        }

    }
}
